package com.example.qjy.korean;

import android.text.TextUtils;
import android.util.Log;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.HashMap;
import java.util.Map;

import static android.content.ContentValues.TAG;

/**
 * Created by qjy on 2017/12/22.
 */

public class KoreanUnicodeUtil {
    String jamo = "{'ㄱ':[14,44032,1],'ㄲ':[6,44620,2],'ㄳ':[4,-1,3],'ㄴ':[14,45208,4]," +
            "'ㄵ':[4,-1,5],'ㄶ':[4,-1,6],'ㄷ':[6,45796,7],'ㄸ':[2,46384,0],'ㄹ':[14,46972,8]," +
            "'ㄺ':[4,-1,9],'ㄻ':[4,-1,10],'ㄼ':[4,-1,11],'ㄽ':[4,-1,12],'ㄾ':[4,-1,13],'ㄿ':[4,-1,14]," +
            "'ㅀ':[4,-1,15],'ㅁ':[6,47560,16],'ㅂ':[14,48148,17],'ㅃ':[2,48736,0],'ㅄ':[4,-1,18]," +
            "'ㅅ':[14,49324,19],'ㅆ':[6,49912,20],'ㅇ':[6,50500,21],'ㅈ':[6,51088,22],'ㅉ':[2,51676,0]," +
            "'ㅊ':[6,52264,23],'ㅋ':[6,52852,24],'ㅌ':[6,53440,25],'ㅍ':[6,54028,26],'ㅎ':[6,54616,27]," +
            "'ㅏ':[1,0,0],'ㅐ':[1,28,0],'ㅑ':[1,56,0],'ㅒ':[1,84,0],'ㅓ':[1,112,0],'ㅔ':[1,140,0]," +
            "'ㅕ':[1,168,0],'ㅖ':[1,196,0],'ㅗ':[1,224,0],'ㅛ':[1,336,0],'ㅜ':[1,364,0],'ㅠ':[1,476,0]," +
            "'ㅡ':[1,504,0],'ㅣ':[1,560,0]}";
    int[] VV2V = new int[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 224, 224, 0, 0, 364, 364, 364, 0, 0, 504, 0};
    String V2VV = "[0,0,0,0,0,0,0,0,{'ㅏ':252,'ㅐ':280,'ㅣ':308},0,0,0,0,{'ㅓ':392,'ㅔ':420,'ㅣ':448},0,0,0,0, {'ㅣ':532},0,0]";
    String CV2CString = "ㄱㄲㄴㄷㄸㄹㅁㅂㅃㅅㅆㅇㅈㅉㅊㅋㅌㅍㅎ";
    char[] CV2V = CV2CString.toCharArray();
    int[] PP2P = new int[]{0, 0, 1, 1, 0, 4, 4, 0, 0, 8, 8, 8, 8, 8, 8, 8, 0, 0, 17, 0, 19, 0, 0, 0, 0, 0, 0, 0};

    Map<String, String> C2CCMap = new HashMap<>();
    Map<String, String> CC2CMap = new HashMap<>();

    String PP2PC = "[0,[0,44032],[0,44620],[1,49324],[0,45208],[4,51088],[4,54616],[0,45796]," +
            "[0,46972],[8,44032],[8,47560],[8,48148],[8,49324],[8,53440],[8,54028],[8,54616]," +
            "[0,47560],[0,48148],[17,49324],[0,49324],[0,49912],[0,50500],[0,51088],[0,52264]," +
            "[0,52852],[0,53440],[0,54028],[0,54616]]";
    String P2PP = "[0,{'ㄱ':2, 'ㅅ':3},0,0,{'ㅈ':5, 'ㅎ':6},0,0,0,{'ㄱ':9,'ㅁ':10," +
            "'ㅂ':11,'ㅅ':12,'ㅌ':13,'ㅍ':14,'ㅎ':15},0,0,0,0,0,0,0,0,{'ㅅ':18},0,{'ㅅ':20},0,0,0,0,0,0,0,0]";
    int flags = 0; //for some crosstalk

    public KoreanUnicodeUtil() {
        C2CCMap.put("ㄱ", "ㄲ");
        C2CCMap.put("ㄷ", "ㄸ");
        C2CCMap.put("ㅂ", "ㅃ");
        C2CCMap.put("ㅅ", "ㅆ");
        C2CCMap.put("ㅈ", "ㅉ");
        CC2CMap.put("ㄲ", "ㄱ");
        CC2CMap.put("ㄸ", "ㄷ");
        CC2CMap.put("ㅃ", "ㅂ");
        CC2CMap.put("ㅆ", "ㅅ");
        CC2CMap.put("ㅉ", "ㅈ");
    }

    public int[] parseHangul(String bufchar) {
        if (TextUtils.isEmpty(bufchar) || bufchar.length() > 1) return null;
        char codeChar = bufchar.toCharArray()[0];
        int code = codeChar;
        if (code < 0x3131 || code > 0xD7A3) return null;
        else if (code < 0x314F && code > 0x3130) return new int[]{parseJamo(bufchar)[1], -1, 0};
        code -= 44032;
        int[] arr = new int[3];
        arr[0] = 44032 + 588 * (code / 588 >> 0);
        code %= 588;
        arr[1] = 28 * (code / 28 >> 0);
        arr[2] = code % 28;
        return arr;
    }

    public int[] parseJamo(String bufchar) {
        int[] ints = new int[3];
        try {
            JSONObject jsonObject = new JSONObject(jamo);
            JSONArray jsonArray = jsonObject.getJSONArray(bufchar);
            for (int i = 0; i < jsonArray.length(); i++) {
                ints[i] = jsonArray.getInt(i);
            }
        } catch (JSONException e) {
            e.printStackTrace();
            return null;
        }
        return ints;
    }

    public int parseP2PP(int index, String chr) {
        int parseInt = 0;
        try {
            JSONArray jsonArray = new JSONArray(P2PP);
            JSONObject jsonObject = jsonArray.getJSONObject(index);
            parseInt = jsonObject.getInt(chr);
        } catch (JSONException e) {
            e.printStackTrace();
            return 0;
        }
        return parseInt;
    }

    public int parsePP2PC(int index,int position){
        int parseInt = 0;
        try {
            JSONArray jsonArray = new JSONArray(PP2PC);
            JSONArray jsonArray1 = jsonArray.getJSONArray(index);
            parseInt = jsonArray1.getInt(position);
        } catch (JSONException e) {
            e.printStackTrace();
            return 0;
        }
        return parseInt;
    }

    public int parseV2VV(int index,String chr){
        int parseInt = 0;
        try {
            JSONArray jsonArray = new JSONArray(V2VV);
            JSONObject jsonObject = jsonArray.getJSONObject(index);
            parseInt = jsonObject.getInt(chr);
        } catch (JSONException e) {
            e.printStackTrace();
            return 0;
        }
        return parseInt;
    }

    public String[] charProcessor(String chr, String buf, int[] CVC,boolean runbd) {
        int[] jamo = parseJamo(chr);
        if (CVC == null) CVC = parseHangul(buf);
        if (CVC == null) {
            if (jamo == null) {
                return new String[]{chr, "0"};
            } else {
                if ((jamo[0] & 2) != 0) return new String[]{chr, "1"};
                else return new String[]{chr, "0"};
            }
        } else {
            if (chr.equals("\\u0008")) {
                if (CVC[2] != 0) {
                    return new String[]{new String(new int[]{CVC[0] + CVC[1] + PP2P[CVC[2]]}, 0, 1), "1"};
                } else if (CVC[1] > -1) {
                    int VV2VInt = VV2V[CVC[1] / 28];
                    if (VV2VInt != 0)
                        return new String[]{new String(new int[]{CVC[0] + VV2VInt}, 0, 1), "1"};
                    else
                        return new String[]{new String(new char[]{CV2V[(CVC[0] - 44032) / 588]}), "1"};
                } else if (!TextUtils.isEmpty(CC2CMap.get(buf))) {
                    return new String[]{CC2CMap.get(buf), "1"};
                } else {
                    flags = 0;
                    return new String[]{" ", "0"};
                }
            } else if (jamo == null) {
                flags = 0;
                return new String[]{buf + chr, "0"};
            } else if (CVC[2] != 0) {
                if ((jamo[0] & 2) != 0) {
                    int parseP2PP = parseP2PP(CVC[2], chr);
                    if (parseP2PP!=0) return new String[]{new String(new int[]{CVC[0]+CVC[1]+parseP2PP}, 0, 1),"1"};
                    else return new String[]{buf + chr,"1"};
                }else if ((jamo[0]&1)!=0){
                    Log.e(TAG, "charProcessor: parsePP2PC(CVC[2],1)+parseJamo(chr)[1]"+parsePP2PC(CVC[2],1)+"---"+parseJamo(chr)[1] );
                    if (runbd && CVC[2] == 21)
                        return new String[]{buf+new String(new int[]{50500+jamo[1]}, 0, 1)};
                    return new String[]{new String(new int[]{CVC[0]+CVC[1]+parsePP2PC(CVC[2],0)}, 0, 1)
                            + new String(new int[]{parsePP2PC(CVC[2],1)+parseJamo(chr)[1]}, 0, 1) ,"1" };
                }else {
                    return new String[]{buf+chr,"0"};
                }
            }else if (CVC[1]>-1){
                flags &=~ 3;
                if ((jamo[0] & 4)!=0){
                    return new String[]{new String(new int[]{CVC[0]+CVC[1]+jamo[2]},0,1),"1"};
                }else if ((jamo[0] & 1)!=0){
                    if (runbd){
                        int vow = "\\u3153\\u3154\\u3163".indexOf(chr);
                        if ((flags & 4)!=0 && vow!=-1){
                            flags &=~4;
                            return new String[]{new String(new int[]{CVC[0]+new int[]{392,308,448}[vow]},0,1),"1"};
                        }
                    }
                    int intV2VV = parseV2VV(CVC[1]/28,chr);
                    if (intV2VV!=0){
                        return new String[]{new String(new int[]{CVC[0]+intV2VV},0,1),"1"};
                    }else {
                        if (runbd){
                            return new String[]{buf+new String(new int[]{50500+jamo[1]},0,1),"1"};
                        }else return new String[]{buf+chr,"0"};
                    }
                }else return new String[]{buf+chr,"1"};
            }else if ((jamo[0]&1)!=0){
                return new String[]{new String(new int[]{parseJamo(buf)[1]+jamo[1]},0,1),"1"};
            }else {
                if (buf.equals(chr) && !TextUtils.isEmpty(C2CCMap.get(buf)))return new String[]{C2CCMap.get(buf),"1"};
                else return new String[]{buf+chr,"1"};
            }
        }
    }
}
